package com.winning.pmph.ctrl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.winning.pmph.utils.StringUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.winning.pmph.config.CommonConfig;
import com.winning.pmph.entity.IncreaseBook;
import com.winning.pmph.entity.IncreaseBookQrdiy;
import com.winning.pmph.entity.IncreaseQrCode;
import com.winning.pmph.entity.IncreaseQrDiy;
import com.winning.pmph.entity.IncreaseResource;
import com.winning.pmph.entity.IncreaseResourceSub;
import com.winning.pmph.service.IncreaseBookQrdiyService;
import com.winning.pmph.service.IncreaseBookService;
import com.winning.pmph.service.IncreaseQrCodeService;
import com.winning.pmph.service.IncreaseQrDiyService;
import com.winning.pmph.service.IncreaseResourceService;
import com.winning.pmph.service.IncreaseResourceSubService;
import com.winning.pmph.utils.ApplicationContextUtil;
import com.winning.pmph.utils.ExecutorServiceFactory;
import com.winning.pmph.utils.PMPHAppUtil;
import com.winning.pmph.utils.QrcodeUtils;
import com.winning.pmph.vo.ResultData;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ZipUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author lbm
 * @since 2021-12-30
 */
@Api(value = "图书增值服务生码管理")
@RestController
@RequestMapping("/pmph/action/increaseQrCode")
public class IncreaseQrCodeCtrl{

    @Resource
    IncreaseQrCodeService increaseQrCodeService;

    @Resource
    IncreaseBookQrdiyService increaseBookQrdiyService;

    @Resource
    IncreaseQrDiyService increaseQrDiyService;

    @Resource
    IncreaseResourceService increaseResourceService;
    
    @Resource
    IncreaseBookService increaseBookService;
    
    @Autowired
    private IncreaseResourceSubService increaseResourceSubService;
    /**
     * 素材码列表
     * @param bookId
     * @param qrName
     * @param resourceType
     * @param start
     * @param size
     * @return
     */
    @ApiOperation(value = "selectListResourceQr", notes = "素材码列表")
    @GetMapping("selectListResourceQr")
    public ResultData<Map<String, Object>> selectListResourceQr(String bookId, String qrName, String resourceType, int start, int size) {
        Map<String, Object> resp = new HashMap<>();
        resp.put("datas", this.increaseQrCodeService.list(bookId, qrName, resourceType, start, size));
        resp.put("total", this.increaseQrCodeService.listCount(bookId, qrName, resourceType));
        return ResultData.success(resp);
    }

    /**
     * 生成素材码
     * @param bookId
     * @param resourceName 资源名称（二维码文件名）
     * @param resourceSuffix 资源文件后缀
     * @param qrName 二维码名（二维码左上角显示文字）
     * @return
     */
    @ApiOperation(value = "generateResQr", notes = "素材码生成")
    @RequestMapping("generateResQr")
    public ResultData<String> generateResQr(String bookId, String resourceId, String resourceName, String resourceSuffix, String qrName) throws Exception {
        List<IncreaseQrDiy> qrDiyList = this.increaseQrDiyService.lambdaQuery().ne(IncreaseQrDiy::getType, 2).list();
        String[] resourceIds = resourceId.split(",");
        String[] resourceNames = resourceName.split(",");
        String[] resourceSuffixs = resourceSuffix.split(",");
        String[] qrNames = qrName.split(",");
        if(StringUtils.isBlank(resourceId)) {
            List<Map<String, Object>> allResList = this.increaseQrCodeService.list(bookId, qrName, null, -1, -1);
            resourceIds = new String[allResList.size()];
            resourceNames = new String[allResList.size()];
            resourceSuffixs = new String[allResList.size()];
            qrNames = new String[allResList.size()];
            for(int i=0;i<allResList.size();i++) {
                Map<String, Object> map = allResList.get(i);
                resourceIds[i] = map.get("res_id").toString();
                resourceNames[i] = map.get("res_name").toString();
                resourceSuffixs[i] = map.get("res_suffix").toString();
                if(map.get("name") != null && StringUtils.isNotBlank(map.get("name").toString())) {
                    qrNames[i] = map.get("name").toString();
                }else {
                    qrNames[i] = map.get("res_name").toString();
                }
            }
        }
        for(int i=0; i<resourceIds.length; i++) {
            IncreaseQrDiy qrDiyConfig = null;
            for (IncreaseQrDiy qrDiy : qrDiyList) {
            	if(qrDiy.getType()==3) {
            		if("group".equals(resourceSuffixs[i])) {
            			qrDiyConfig = qrDiy;
                		break;
            		}
            	}else {
            		String[] suffixs = qrDiy.getResourceSuffix().split(",");
                    for (String suffix : suffixs) {
                        if (suffix.equalsIgnoreCase(resourceSuffixs[i])) {
                            qrDiyConfig = qrDiy;
                            break;
                        }
                    }
            	}
            }
            if (qrDiyConfig != null) {
                List<IncreaseBookQrdiy> bookQrdiyList = this.increaseBookQrdiyService.lambdaQuery()
                        .eq(IncreaseBookQrdiy::getBookId, bookId)
                        .eq(IncreaseBookQrdiy::getQrDiyId, qrDiyConfig.getId()).orderByDesc(IncreaseBookQrdiy::getId).list();
                String qrCodePath = ApplicationContextUtil.BASE_DOWN_FORDER + "qrCode/" + bookId + "/resqr/" + resourceNames[i] + ".png";
                String qrCodeUrl = CommonConfig.rsUrl+"?id="+resourceIds[i]+"&t=2";
//                int resourceType = FfmpegUtil.getResourceType("." + resourceSuffixs[i]);
//                if(resourceType == 1) {
//                    qrCodeUrl = qrCodeUrl + "detail_image?resourceId=" + resourceIds[i];
//                }else if(resourceType == 2) {
//                    qrCodeUrl = qrCodeUrl + "detail_video?resourceId=" + resourceIds[i];
//                }else if(resourceType == 5 || resourceType==6) {
//                    qrCodeUrl = qrCodeUrl + "detail_ppt?resourceId=" + resourceIds[i];
//                }else if(resourceType == 7) {
//                    qrCodeUrl = qrCodeUrl + "detail_audio?resourceId=" + resourceIds[i];
//                }
                if (bookQrdiyList != null && bookQrdiyList.size() != 0) {
                    QrcodeUtils.generateQrCode(qrCodeUrl, qrNames[i],
                            ApplicationContextUtil.BASE_DOWN_FORDER + bookQrdiyList.get(0).getLogo(), qrCodePath);
                } else {
                    QrcodeUtils.generateQrCode(qrCodeUrl, qrNames[i],
                            ApplicationContextUtil.BASE_DOWN_FORDER + qrDiyConfig.getLogo(), qrCodePath);
                }
                IncreaseQrCode increaseQrCode = this.increaseQrCodeService.lambdaQuery().eq(IncreaseQrCode::getSourceId, resourceIds[i]).one();
                if(increaseQrCode == null) {
                    increaseQrCode = new IncreaseQrCode();
                }
                increaseQrCode.setCode("/qrCode/" + bookId + "/resqr/" + resourceNames[i] + ".png");
                increaseQrCode.setCreateTime(DateUtil.now());
                increaseQrCode.setSourceType(2);
                increaseQrCode.setSourceId(resourceIds[i]);
                increaseQrCode.setName(qrNames[i]);
                if(StringUtils.isNotBlank(increaseQrCode.getId())) {
                    this.increaseQrCodeService.updateById(increaseQrCode);
                }else {
                    this.increaseQrCodeService.save(increaseQrCode);
                }
            }
        }
        try {
        	increaseBookService.syncBookData();
		} catch (Exception e) {
			e.printStackTrace();
		}
        return ResultData.success(null);
    }

    /**
     * 导出图书素材码
     * @param bookId
     * @return
     */
    @ApiOperation(value = "exportResQr", notes = "导出素材码")
    @RequestMapping("exportResQr")
    @ResponseBody
    public ResultData<Map<String,String>> exportResQr(String bookId, String bookName, String resId) throws Exception {
        List<Map<String, Object>> resQrList = this.increaseQrCodeService.list(bookId, null, null, -1, -1);
        Stream<Map<String, Object>> stream = resQrList.stream().filter(resQr -> resQr.get("code") != null && StringUtils.isNotBlank(resQr.get("code").toString()));
        if(StringUtils.isNotBlank(resId)) {
            stream = stream.filter(resQr -> resId.contains(resQr.get("res_id").toString()));
        }
        List<String> qrPathList = stream.map(resQr -> ApplicationContextUtil.BASE_DOWN_FORDER + resQr.get("code").toString()).collect(Collectors.toList());
        List<String> paths = QrcodeUtils.export(qrPathList, ApplicationContextUtil.BASE_DOWN_FORDER + "qrcode/" + bookId + "/resqr/export/" + bookName);
        if(paths.size() != 0) {
            qrPathList.addAll(paths);
        }
        String[] srcPaths = new String[qrPathList.size()];
        InputStream[] srcIns = new InputStream[qrPathList.size()];
        for(int i=0; i<qrPathList.size(); i++) {
            srcPaths[i] = FileUtil.getName(qrPathList.get(i));
            srcIns[i] = FileUtil.getInputStream(qrPathList.get(i));
        }
        File zipFile = new File(ApplicationContextUtil.BASE_DOWN_FORDER + "qrcode/" + bookId + "/resqr/export/" + bookName + ".zip");
        if(zipFile.exists()) {
            zipFile.delete();
        }
        try {
            if(srcPaths.length<=0){
                return ResultData.fail("该图书下无二维码文件");
            }
            ZipUtil.zip(zipFile, srcPaths, srcIns, StandardCharsets.UTF_8);
        }finally {
            for(InputStream in : srcIns) {
                IoUtil.close(in);
            }
        }
        Map<String,String> map = new HashMap<>();
        map.put("path","qrcode/" + bookId + "/resqr/export/" + bookName + ".zip");
        return ResultData.success(map);
    }

    /**
     * 章节码列表
     * @param bookId
     * @return
     */
    @ApiOperation(value = "selectListChapterQr", notes = "章节码列表")
    @GetMapping("selectListChapterQr")
    public ResultData<List<Map<String, Object>>> selectListChapterQr(String bookId) {
        return ResultData.success(this.increaseQrCodeService.treeChapterQr(bookId));
    }

    /**
     * 生成章节码
     * @param bookId
     * @param chapterId
     * @param qrName
     * @return
     */
    @ApiOperation(value = "generateChapterQr", notes = "生成章节码")
    @RequestMapping("generateChapterQr")
    public ResultData<String> generateChapterQr(String bookId, String chapterId, String qrName, String resPath) throws Exception {

        IncreaseQrDiy qrDiyConfig = this.increaseQrDiyService.lambdaQuery().eq(IncreaseQrDiy::getType, 2).one();
        String qrLogo = qrDiyConfig.getLogo();
        List<IncreaseBookQrdiy> bookQrdiyList = this.increaseBookQrdiyService.lambdaQuery()
                .eq(IncreaseBookQrdiy::getBookId, bookId)
                .eq(IncreaseBookQrdiy::getQrDiyId, qrDiyConfig.getId()).list();
        if(bookQrdiyList.size() != 0) {
            qrLogo = bookQrdiyList.get(0).getLogo();
        }
        if(StringUtils.isBlank(qrLogo)) {
            return ResultData.fail("二维码logo缺失");
        }
        String[] chapterIds = chapterId.split(",");
        String[] qrNames = qrName.split(",");
        String[] resPaths = resPath.split(",");
        for(int i=0; i<chapterIds.length; i++) {
            if("no".equals(resPaths[i])) {
                continue;
            }
            String[] resIdPath = resPaths[i].split("`");
            String qrCodePath = ApplicationContextUtil.BASE_DOWN_FORDER + "qrCode/" + bookId + "/chapterqr/" + chapterIds[i] + ".png";
            String qrCodeUrl = CommonConfig.rsUrl+"?id="+resIdPath[0]+","+chapterIds[i]+"&t=2";
//            int resourceType = FfmpegUtil.getResourceType("." + FileUtil.extName(resIdPath[1]));
//            if(resourceType == 1) {
//                qrCodeUrl = qrCodeUrl + "detail_image?resourceId=" + resIdPath[0];
//            }else if(resourceType == 2) {
//                qrCodeUrl = qrCodeUrl + "detail_video?resourceId=" + resIdPath[0];
//            }else if(resourceType == 5) {
//                qrCodeUrl = qrCodeUrl + "detail_ppt?resourceId=" + resIdPath[0];
//            }else if(resourceType == 7) {
//                qrCodeUrl = qrCodeUrl + "detail_audio?resourceId=" + resIdPath[0];
//            }
            QrcodeUtils.generateQrCode(qrCodeUrl, qrNames[i],
                        ApplicationContextUtil.BASE_DOWN_FORDER + qrLogo, qrCodePath);

            IncreaseQrCode increaseQrCode = this.increaseQrCodeService.lambdaQuery().eq(IncreaseQrCode::getSourceId, chapterIds[i]).one();
            if(increaseQrCode == null) {
                increaseQrCode = new IncreaseQrCode();
            }
            increaseQrCode.setName(qrNames[i]);
            increaseQrCode.setCode("/qrCode/" + bookId + "/chapterqr/" + chapterIds[i] + ".png");
            increaseQrCode.setCreateTime(DateUtil.now());
            increaseQrCode.setSourceType(1);
            increaseQrCode.setSourceId(chapterIds[i]);
            if(StringUtils.isNotBlank(increaseQrCode.getId())) {
                this.increaseQrCodeService.updateById(increaseQrCode);
            }else {
                this.increaseQrCodeService.save(increaseQrCode);
            }
        }
        try {
        	increaseBookService.syncBookData();
		} catch (Exception e) {
			e.printStackTrace();
		}
        return ResultData.success(null);
    }

    /**
     * 导出图书章节码
     * @param bookId
     * @return
     */
    @ApiOperation(value = "exportChapterQr", notes = "导出图书章节码")
    @RequestMapping("exportChapterQr")
    @ResponseBody
    public ResultData<Map<String,String>> exportChapterQr(String bookId, String bookName, String resId) throws Exception {
        List<Map<String, Object>> resQrList = this.increaseQrCodeService.listChapterQr(bookId);
        Stream<Map<String, Object>> stream = resQrList.stream().filter(resQr -> resQr.get("code") != null && StringUtils.isNotBlank(resQr.get("code").toString()));
        if(StringUtils.isNotBlank(resId)) {
            stream = stream.filter(resQr -> resId.contains(resQr.get("id").toString()));
        }
        List<String> qrPathList = stream.map(resQr -> ApplicationContextUtil.BASE_DOWN_FORDER + resQr.get("code").toString()).collect(Collectors.toList());
        List<String> paths = QrcodeUtils.export(qrPathList, ApplicationContextUtil.BASE_DOWN_FORDER + "qrcode/" + bookId + "/chapterqr/export/" + bookName);
        if(paths.size() != 0) {
            qrPathList.addAll(paths);
        }
        String[] srcPaths = new String[qrPathList.size()];
        InputStream[] srcIns = new InputStream[qrPathList.size()];
        for(int i=0; i<qrPathList.size(); i++) {
            srcPaths[i] = FileUtil.getName(qrPathList.get(i));
            srcIns[i] = FileUtil.getInputStream(qrPathList.get(i));
        }
        File zipFile = new File(ApplicationContextUtil.BASE_DOWN_FORDER + "qrcode/" + bookId + "/chapterqr/export/" + bookName + ".zip");
        if(zipFile.exists()) {
            zipFile.delete();
        }
        try {
            if(srcPaths.length<=0){
                return ResultData.fail("该图书下无二维码文件");
            }
            ZipUtil.zip(zipFile, srcPaths, srcIns, StandardCharsets.UTF_8);
        }finally {
            for(InputStream in : srcIns) {
                IoUtil.close(in);
            }
        }
        Map<String,String> map = new HashMap<>();
        map.put("path","qrcode/" + bookId + "/chapterqr/export/" + bookName + ".zip");
        return ResultData.success(map);
    }

    @ApiOperation(value = "saveQrName", notes = "保存章节码二维码名称")
    @RequestMapping("saveQrName")
    @ResponseBody
    public ResultData<String> saveQrName(String qrId, String qrName, String qrType) throws Exception {
        LambdaQueryChainWrapper<IncreaseQrCode> qw = this.increaseQrCodeService.lambdaQuery()
                .eq(IncreaseQrCode::getName, qrName)
                .eq(IncreaseQrCode::getSourceType, qrType);
        if(StringUtils.isNotBlank(qrId)) {
            qw.ne(IncreaseQrCode::getId, qrId);
        }
        Integer count = qw.count();
        if(count != 0) {
            return ResultData.fail("二维码名称重复");
        }else {
            IncreaseQrCode increaseQrCode = new IncreaseQrCode();
            increaseQrCode.setName(qrName);
            increaseQrCode.setId(qrId);
            this.increaseQrCodeService.saveOrUpdate(increaseQrCode);
        }
        return ResultData.success(null);
    }

    @ApiOperation(value = "listResByCateId", notes = "获取目录下所有资源")
    @RequestMapping("listResByCateId")
    @ResponseBody
    public ResultData<Page<IncreaseResource>> listResByCateId(String cateId, int start, int size) {
        Page<IncreaseResource> page = this.increaseResourceService.lambdaQuery()
                .in(IncreaseResource::getCateId, Arrays.asList(cateId.split(",")))
                .page(new Page<>(start, size));
        return ResultData.success(page);
    }

    @ApiOperation(value = "listPpt", notes = "获取ppt转换的所有图片")
    @RequestMapping("listPpt")
    @ResponseBody
    public ResultData<List<String>> listPpt(String path) throws Exception {
        String pptDir = ApplicationContextUtil.BASE_DOWN_FORDER + path.split("\\.")[0];
        Collection<File> uploadedFiles = FileUtils.listFiles(new File(pptDir), null, true);
        List<File> files = new ArrayList<>(uploadedFiles);
        files.sort((o1, o2) -> {
            int s1 = Integer.parseInt(FileUtil.mainName(o1));
            int s2 = Integer.parseInt(FileUtil.mainName(o2));
            return s1 - s2;
        });
        List<String> paths = files.stream().map(file -> file.getAbsolutePath().replace(ApplicationContextUtil.BASE_DOWN_FORDER, "")).collect(Collectors.toList());
        return ResultData.success(paths);
    }
    
    @ApiOperation(value = "listPptImg", notes = "获取ppt转换的所有图片")
    @RequestMapping("listPptImg")
    @ResponseBody
    public ResultData<List<String>> listPptImg(String id) throws Exception {
        List<String> files = new ArrayList<>();
        List<IncreaseResourceSub> list = increaseResourceSubService.lambdaQuery().eq(IncreaseResourceSub::getResourceId, id).list();
        for(IncreaseResourceSub sub:list) {
        	String path = sub.getImgPath();
        	files.add(path);
        }
        return ResultData.success(files);
    }

    @ApiOperation(value = "play", notes = "音频播放")
    @GetMapping("play")
    public void play(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String fileName = URLDecoder.decode(request.getParameter("filename"), "UTF-8");
        String tempFilePath = ApplicationContextUtil.BASE_DOWN_FORDER + fileName;
        FileInputStream inputStream = new FileInputStream(tempFilePath);
        byte[] data = FileUtils.readFileToByteArray(new File(tempFilePath));
        response.setContentType("audio/mpeg;charset=UTF-8");
//        response.setContentLength(data.length);
//        response.setHeader("Content-Range", "" + Integer.valueOf(data.length - 1));
//        response.setHeader("Accept-Ranges", "bytes");
//        response.setHeader("Etag", "W/\"9767057-1323779115364\"");
        ServletOutputStream os = response.getOutputStream();
        os.write(data);
        //先声明的流后关掉！
        os.flush();
        os.close();
        inputStream.close();
    }

    /**
     * 更新扫码次数，获取资源类型
     * resourceId：分为资源码 或者 章节码
     *  资源码格式：[资源ID]
     *  章节码格式：[资源ID,章节ID] 英文逗号分隔
     */
    @ApiOperation(value = "updateScanCount", notes = "更新扫码次数")
    @GetMapping("updateScanCount")
    public ResultData<IncreaseResource> updateScanCount(String resourceId) throws IOException {
    	try {
    		if(StringUtils.isBlank(resourceId)) {
        		return ResultData.fail("当前二维码不存在");
        	}
            IncreaseQrCode qrCode = null;
            //判断是否包含章节id
            if(resourceId.indexOf(",")>0){
    		    //包含
                String chapterId = resourceId.split(",")[1];
                resourceId = resourceId.split(",")[0];
                //获取章节码信息
                List<IncreaseQrCode> listQr = increaseQrCodeService.lambdaQuery().eq(IncreaseQrCode::getSourceId, chapterId).list();
                if(listQr!=null && listQr.size()>0) {
                    qrCode = listQr.get(0);
                }
            }else{
                //获取资源码信息
                List<IncreaseQrCode> listQr = increaseQrCodeService.lambdaQuery().eq(IncreaseQrCode::getSourceId, resourceId).list();
                if(listQr!=null && listQr.size()>0) {
                    qrCode = listQr.get(0);
                }
            }

            IncreaseResource resource = increaseResourceService.getById(resourceId);
            if(resource==null){
                return ResultData.fail("当前二维码未找到对应资源");
            }
            String bookId = resource.getBookId();
            IncreaseBook book = increaseBookService.getById(bookId);
            if(book==null || book.getPubStatus()==3){
                return ResultData.fail("当前图书不存在或者已删除");
            }
            if(qrCode!=null){
                IncreaseQrCode updateQrCode = new IncreaseQrCode();
                updateQrCode.setId(qrCode.getId());
                if(book.getPubStatus()==1) {
                    //1新建(发布前)
                    Integer count = qrCode.getScanQulityBefore();
                    updateQrCode.setScanQulityBefore(calculateScanCount(count));
                }else if(book.getPubStatus()==2){
                    //2已发布 (发布后)
                    Integer count = qrCode.getScanCountAfter();
                    updateQrCode.setScanCountAfter(calculateScanCount(count));
                }
                increaseQrCodeService.updateById(updateQrCode);
            }
            IncreaseResource result = new IncreaseResource();
            result.setId(resource.getId());
            result.setName(resource.getName());
            result.setResourceType(resource.getResourceType());
            result.setBookId(resource.getBookId());
            return ResultData.success(result);
		} catch (Exception e) {
			e.printStackTrace();
            return ResultData.fail("系统异常，请联系工作人员");
		}
    }
    
    private static Integer calculateScanCount(Integer count) {
    	int num = 0;
    	if(count==null) {
			num = 1;
		}else {
			num = count+1;
		}
    	return num;
    }
}

